package com.zmzncs.lmtc.common.advice;

import com.google.common.collect.Lists;
import com.zmzncs.lmtc.common.exception.AuthorizeException;
import com.zmzncs.lmtc.common.exception.BusinessException;
import com.zmzncs.lmtc.common.exception.ParamException;
import com.zmzncs.lmtc.common.pojo.Rest;
import com.zmzncs.lmtc.common.util.RestUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.*;

import javax.validation.ConstraintViolationException;
import java.util.List;


/**
 *
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    /**
     * 认证异常
     */
    @ExceptionHandler(AuthorizeException.class)
    @ResponseStatus(HttpStatus.OK)
    public Rest businessException(AuthorizeException exception) {
        logger.warn(exception.getMessage());
        return RestUtil.warning(401, exception.getMessage());
    }

    /**
     * 业务异常
     */
    @ExceptionHandler(BusinessException.class)
    @ResponseStatus(HttpStatus.OK)
    public Rest businessException(BusinessException exception) {
        logger.info("异常类型：" + exception.getClass().toString());
        logger.warn(exception.getMessage());
        return RestUtil.warning(403, exception.getMessage());
    }

    /**
     * 参数校验异常
     */
    @ExceptionHandler(ParamException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Rest businessException(ParamException exception) {
        logger.info("异常类型：" + exception.getClass().toString());
        logger.warn(exception.getMessage());
        return RestUtil.warning(400, exception.getMessage());
    }

    /**
     * 请求类型错误ContentType
     */
    @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Rest httpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException exception) {
        logger.info("异常类型：" + exception.getClass().toString());
        logger.warn("ContentType不支持" + exception.getContentType() + "，请使用" + exception.getSupportedMediaTypes());
        return RestUtil.warning(400, "ContentType不支持" + exception.getContentType() + "，请使用" + exception.getSupportedMediaTypes());
    }

    /**
     * 请求方式post，get等
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Rest HttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException exception) {
        logger.info("异常类型：" + exception.getClass().toString());
        logger.warn("请求方式不支持" + exception.getMethod() + "，请使用" + exception.getSupportedHttpMethods());
        return RestUtil.warning(400, "请求方式不支持" + exception.getMethod() + "，请使用" + exception.getSupportedHttpMethods());
    }

    /**
     * BindException参数校验未通过异常
     */
    @ExceptionHandler(BindException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Rest bindException(BindException exception) {
        logger.info("异常类型：" + exception.getClass().toString());

        FieldError fieldError = exception.getBindingResult().getFieldError();
        assert fieldError != null;
        logger.warn(fieldError.getField() + ":" + fieldError.getDefaultMessage());
        return RestUtil.warning(400, "参数错误" , fieldError.getField() + ":" + fieldError.getDefaultMessage());
    }

    /**
     * 参数校验未通过异常 @RequestBody参数校验失败
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Rest methodArgumentNotValidException(MethodArgumentNotValidException exception) {
        logger.info("异常类型：" + exception.getClass().toString());

        List<ObjectError> errors = exception.getBindingResult().getAllErrors();
        StringBuffer sb = new StringBuffer();
        List<String> errorArr = Lists.newArrayList();
        for (ObjectError error : errors) {
            if (error instanceof FieldError){
                FieldError fieldError=(FieldError)error;
                errorArr.add(fieldError.getField()+fieldError.getDefaultMessage());
            }else{
                errorArr.add(error.getObjectName()+error.getDefaultMessage());
            }
        }
        logger.warn("参数错误：" + errorArr.toString());
        return RestUtil.warning(400, "参数错误", errorArr.toArray(new String[]{}));
    }

    /**
     * @RequestParam 参数校验失败
     */
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Rest constraintViolationException(ConstraintViolationException exception) {
        logger.info("异常类型：" + exception.getClass().toString());
        logger.warn("参数错误：" + exception.getMessage());

        return RestUtil.warning(400, "参数错误", exception.getMessage());
    }

    /**
     * 参数类型不匹配
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    public Rest httpMessageNotReadableException(Exception exception){
        logger.info("异常类型：" + exception.getClass().toString());
        logger.warn("参数类型错误：" + exception.getMessage());

        return RestUtil.warning(400, "参数类型错误", exception.getMessage());
    }

    @ExceptionHandler(Exception.class)
    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    public Rest globalException(Exception exception){
        exception.printStackTrace();
        logger.error(exception.getMessage());
        return RestUtil.error("服务器错误", exception.getMessage());
    }


}